package com.mzj.saas.commons;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.Map;

/**
 * @Author: wangrl
 * @Description: HttpRequest 请求工具类
 * @Date: 11:29 2018/5/3
 * @Version: 1.0
 */
public class HttpClientUtil {

	private static final Logger LOG = LoggerFactory.getLogger(HttpClientUtil.class);

	// 连接超时时间，默认10秒
	private static final int socketTimeout = 10000;

	// 传输超时时间，默认30秒
	private static final int connectTimeout = 30000;

	public static String ContentTypeXML = "text/xml"; // xml请求格式

	public static String ContentTypeJSON = "application/json; charset=utf-8"; // JSON请求格式

	/**
	 * url 请求路径 params 参数 contentType 请求头类型
	 * 
	 * @throws IOException
	 * @throws ClientProtocolException
	 * @throws NoSuchAlgorithmException
	 * @throws KeyStoreException
	 * @throws KeyManagementException
	 * @throws UnrecoverableKeyException
	 */
	public static String httpPost(String url, String postData, String contentType) {

		CloseableHttpClient httpClient = null;

		if (url.startsWith("https")) {
			SSLContext sslcontext = null;
			try {
				sslcontext = createIgnoreVerifySSL();
			} catch (KeyManagementException | NoSuchAlgorithmException e) {
				LOG.error(e.getMessage(), e);
				return null;
			}
			Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
					.register("http", PlainConnectionSocketFactory.INSTANCE)
					.register("https", new SSLConnectionSocketFactory(sslcontext)).build();
			PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(
					socketFactoryRegistry);
			connManager.setValidateAfterInactivity(3000);
			HttpClients.custom().setConnectionManager(connManager);

			httpClient = HttpClients.custom().setConnectionManager(connManager).build();
		} else {
			httpClient = HttpClients.createDefault();
		}

		HttpPost httpPost = new HttpPost(url);
		// 得指明使用UTF-8编码，否则到API服务器XML的中文不能被成功识别
		StringEntity postEntity = new StringEntity(postData, "UTF-8");

		if (StringUtils.isEmpty(contentType)) {
			contentType = "application/json";
		}
		httpPost.addHeader("Content-Type", contentType);
		httpPost.setEntity(postEntity);

		// 设置请求器的配置
		// 构建请求配置信息
		RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(connectTimeout) // 创建连接的最长时间
				.setConnectionRequestTimeout(500) // 从连接池中获取到连接的最长时间
				.setSocketTimeout(socketTimeout) // 数据传输的最长时间
				.build();
		httpPost.setConfig(requestConfig);

		CloseableHttpResponse response = null;
		try {
			response = httpClient.execute(httpPost);
			if (response.getStatusLine().getStatusCode() == 200) {
				return EntityUtils.toString(response.getEntity(), "UTF-8");
			}
		} catch (IOException e) {
			e.printStackTrace();

		} finally {
			if (response != null) {
				try {
					response.close();
				} catch (IOException e) {
					LOG.error(e.getMessage(), e);
				}
			}
			if (httpClient != null) {
				try {
					httpClient.close();
				} catch (IOException e) {
					LOG.error(e.getMessage(), e);
				}
			}
		}
		return null;
	}

	/**
	 * 
	 * @param url
	 * @param contentType 默认为application/json
	 * @return
	 * @throws Exception
	 */
	public static String httpGet(String url, String contentType) {

		CloseableHttpClient httpClient = null;

		if (url.startsWith("https")) {
			SSLContext sslcontext = null;
			try {
				sslcontext = createIgnoreVerifySSL();
			} catch (KeyManagementException | NoSuchAlgorithmException e) {
				LOG.error(e.getMessage(), e);
				return null;
			}
			Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
					.register("http", PlainConnectionSocketFactory.INSTANCE)
					.register("https", new SSLConnectionSocketFactory(sslcontext)).build();
			PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(
					socketFactoryRegistry);
			connManager.setValidateAfterInactivity(3000);
			HttpClients.custom().setConnectionManager(connManager);

			httpClient = HttpClients.custom().setConnectionManager(connManager).build();
		} else {
			httpClient = HttpClients.createDefault();
		}

		StringBuffer stringBuffer = new StringBuffer();
		stringBuffer.append(url);

		// 创建http GET请求
		HttpGet httpGet = new HttpGet(stringBuffer.toString());

		if (StringUtils.isEmpty(contentType)) {
			contentType = "application/json";
		}
		httpGet.addHeader("Content-Type", contentType);
		// 构建请求配置信息
		RequestConfig config = RequestConfig.custom().setConnectTimeout(connectTimeout) // 创建连接的最长时间
				.setConnectionRequestTimeout(500) // 从连接池中获取到连接的最长时间
				.setSocketTimeout(socketTimeout) // 数据传输的最长时间
				.build();
		// 设置请求配置信息
		httpGet.setConfig(config);
		CloseableHttpResponse response = null;
		try {
			response = httpClient.execute(httpGet);
			if (response.getStatusLine().getStatusCode() == 200) {
				return EntityUtils.toString(response.getEntity(), "UTF-8");
			}
		} catch (IOException e) {
			e.printStackTrace();

		} finally {
			if (response != null) {
				try {
					response.close();
				} catch (IOException e) {
					LOG.error(e.getMessage(), e);
				}
			}
			if (httpClient != null) {
				try {
					httpClient.close();
				} catch (IOException e) {
					LOG.error(e.getMessage(), e);
				}
			}
		}
		return null;
	}

	public static byte[] httpGetForByte(String url, Map<String, Object> params) throws Exception {
		int i = 0;
		StringBuffer stringBuffer = new StringBuffer();
		stringBuffer.append(url);
		for (Map.Entry<String, Object> entry : params.entrySet()) {
			stringBuffer.append(i == 0 ? "?" : "&").append(entry.getKey()).append("=" + entry.getValue());
			i++;
		}
		// 创建Httpclient对象
		CloseableHttpClient httpclient = HttpClients.createDefault();
		// 创建http GET请求
		HttpGet httpGet = new HttpGet(stringBuffer.toString());
		// 构建请求配置信息
		RequestConfig config = RequestConfig.custom().setConnectTimeout(connectTimeout) // 创建连接的最长时间
				.setConnectionRequestTimeout(500) // 从连接池中获取到连接的最长时间
				.setSocketTimeout(socketTimeout) // 数据传输的最长时间
				.setStaleConnectionCheckEnabled(true) // 提交请求前测试连接是否可用
				.build();
		// 设置请求配置信息
		httpGet.setConfig(config);
		CloseableHttpResponse response = null;
		try {
			// 执行请求
			response = httpclient.execute(httpGet);
			// 判断返回状态是否为200
			if (response.getStatusLine().getStatusCode() == 200) {
				return EntityUtils.toByteArray(response.getEntity());
			}
		} finally {
			if (response != null) {
				response.close();
			}
			httpclient.close();
		}
		return null;
	}

	/**
	 * 绕过验证
	 * 
	 * @return
	 * @throws NoSuchAlgorithmException
	 * @throws KeyManagementException
	 */
	private static SSLContext createIgnoreVerifySSL() throws NoSuchAlgorithmException, KeyManagementException {
		SSLContext sc = SSLContext.getInstance("SSLv3");

		// 实现一个X509TrustManager接口，用于绕过验证，不用修改里面的方法
		X509TrustManager trustManager = new X509TrustManager() {
			@Override
			public void checkClientTrusted(java.security.cert.X509Certificate[] paramArrayOfX509Certificate,
					String paramString) throws CertificateException {
			}

			@Override
			public void checkServerTrusted(java.security.cert.X509Certificate[] paramArrayOfX509Certificate,
					String paramString) throws CertificateException {
			}

			@Override
			public java.security.cert.X509Certificate[] getAcceptedIssuers() {
				return null;
			}
		};

		sc.init(null, new TrustManager[] { trustManager }, null);
		return sc;
	}

	/**
	 * GET请求
	 * 
	 * @param url    请求路径
	 * @param params 参数
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("deprecation")
	public static String httpGetOfParams(String url, Map<String, Object> params) throws Exception {
		int i = 0;
		StringBuffer stringBuffer = new StringBuffer();
		stringBuffer.append(url);
		for (Map.Entry<String, Object> entry : params.entrySet()) {
			stringBuffer.append(i == 0 ? "?" : "&").append(entry.getKey()).append("=" + entry.getValue());
			i++;
		}
		
		// 创建Httpclient对象
		CloseableHttpClient httpclient = HttpClients.createDefault();
		// 创建http GET请求
		HttpGet httpGet = new HttpGet(stringBuffer.toString());
		// 构建请求配置信息
		RequestConfig config = RequestConfig.custom().setConnectTimeout(connectTimeout) // 创建连接的最长时间
				.setConnectionRequestTimeout(500) // 从连接池中获取到连接的最长时间
				.setSocketTimeout(socketTimeout) // 数据传输的最长时间
				.setStaleConnectionCheckEnabled(true) // 提交请求前测试连接是否可用
				.build();
		// 设置请求配置信息
		httpGet.setConfig(config);
		
		CloseableHttpResponse response = null;
		try {
			// 执行请求
			response = httpclient.execute(httpGet);
			// 判断返回状态是否为200
			if (response.getStatusLine().getStatusCode() == 200) {
				return EntityUtils.toString(response.getEntity(), "UTF-8");
			}
		} finally {
			if (response != null) {
				response.close();
			}
			httpclient.close();
		}
		
		return null;
	}
	
}
